#pragma once

#include <Windows.h>
#include <zmouse.h>
#include "../SystemEventArgs.h"

#ifndef GET_WHEEL_DELTA_WPARAM
#define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))
#endif
class Win32EventArgs: public SystemEventArgs
{
public:
	Win32EventArgs(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, CommandState* pCommandState = NULL)
		: SystemEventArgs(pCommandState)
	{
		m_winMessenge.hwnd = hwnd;
		m_winMessenge.message = msg;
		m_winMessenge.wParam = wParam;
		m_winMessenge.lParam = lParam;
		m_winMessenge.time = ::GetTickCount();
	}
	Win32EventArgs(MSG* pMsg, CommandState* pCommandState = NULL)
		: SystemEventArgs(pCommandState)
	{
		if (pMsg != NULL)
			m_winMessenge = *pMsg;
		else
		{
			m_winMessenge.hwnd = NULL;
			m_winMessenge.message = 0;
			m_winMessenge.wParam = 0;
			m_winMessenge.lParam = 0;
			m_winMessenge.time = ::GetTickCount();
		}
	}

	virtual bool LButtonDn() const
	{
		return (m_winMessenge.message == WM_LBUTTONDOWN);
	}
	virtual bool RButtonDn() const
	{
		return (m_winMessenge.message == WM_RBUTTONDOWN);
	}
	virtual bool MButtonDn() const
	{
		return (m_winMessenge.message == WM_MBUTTONDOWN);
	}
	virtual bool LButtonUp() const
	{
		return (m_winMessenge.message == WM_LBUTTONUP);
	}
	virtual bool RButtonUp() const
	{
		return (m_winMessenge.message == WM_RBUTTONUP);
	}
	virtual bool MButtonUp() const
	{
		return (m_winMessenge.message == WM_MBUTTONUP);
	}

	virtual bool MouseMove() const
	{
		return (m_winMessenge.message == WM_MOUSEMOVE);
	}
	virtual bool MouseWheel() const
	{
		return (m_winMessenge.message == WM_MOUSEWHEEL);
	}
	virtual bool LButtonDblClick() const
	{
		return (m_winMessenge.message == WM_LBUTTONDBLCLK);
	}
	virtual bool RButtonDblClick() const
	{
		return (m_winMessenge.message == WM_RBUTTONDBLCLK);
	}

	virtual bool LeftAltKeyDown() const
	{
		return (::GetKeyState(VK_LMENU) & 0x8000) != 0;
	}
	virtual bool RightAltKeyDown() const
	{
		return (::GetKeyState(VK_RMENU) & 0x8000) != 0;
	}
	virtual bool LeftCtrlKeyDown() const
	{
		return (::GetKeyState(VK_LCONTROL) & 0x8000) != 0;
	}
	virtual bool RightCtrlKeyDown() const
	{
		return (::GetKeyState(VK_RCONTROL) & 0x8000) != 0;
	}
	virtual bool LeftShiftKeyDown() const
	{
		return (::GetKeyState(VK_LSHIFT) & 0x8000) != 0;
	}
	virtual bool RightShiftKeyDown() const
	{
		return (::GetKeyState(VK_RSHIFT) & 0x8000) != 0;
	}
	virtual bool CapsLockKeyDown() const
	{
		return (::GetKeyState(VK_CAPITAL) & 0x8000) != 0;
	}
	virtual bool NumLockKeyDown() const
	{
		return (::GetKeyState(VK_NUMLOCK) & 0x8000) != 0;
	}
	virtual vSysChar GetChar() const
	{
		return (vSysChar)m_winMessenge.wParam;
	}
	virtual vSysVirtualKey GetVirtualKey() const
	{
		return (vSysVirtualKey)m_winMessenge.wParam;
	}
	virtual Point GetPhysicalLocation() const
	{
		POINT pt;

		pt.x = LOWORD(m_winMessenge.lParam);
		pt.y = HIWORD(m_winMessenge.lParam);

		if ((m_window != NULL) && (m_winMessenge.message != WM_MOUSEWHEEL))
			::ClientToScreen(m_window , &pt);

		return Point(pt.x,pt.y);
	}
	virtual short GetWheelDelta() const
	{
		return GET_WHEEL_DELTA_WPARAM(m_winMessenge.wParam);
	}
	virtual UINT GetCommandID() const
	{
		if (m_commandState != NULL)
			return m_commandState->nCmdID;
		else
			return LOWORD(m_winMessenge.wParam);
	}
	virtual UINT GetSysCommandID() const
	{
		return (UINT)m_winMessenge.wParam;
	}

protected:
	MSG m_winMessenge;
};